#-*- codeing = utf-8 -*-
#@Time : 2020/10/18 23:20
#@Author : 阳某
#@File : stack和pivot实现数据透视.py
#@Software : PyCharm

'''
将列式数据变成二维交叉形式，便于分析，叫做重塑或透视
经过统计得到多维度指标数据
使用unstack实现数据二维透视
使用pivot简化透视
stack、unstack、pivot的语法
'''

# 1. 经过统计得到多维度指标数据
# 非常常见的统计场景，指定多个维度，计算聚合后的指标
#
# 实例：统计得到“电影评分数据集”，每个月份的每个分数被评分多少次：（月份、分数1~5、次数）
import pandas as pd
import numpy as np
df = pd.read_csv(
    "./files/ratings.dat",
    header=None,
    names="UserID::MovieID::Rating::Timestamp".split("::"),
    sep="::",
    engine="python"
)
print(df.head())
df['pdate'] = pd.to_datetime(df['Timestamp'],unit='s')
print(df.head())
print(df.dtypes)
# 实现数据统计
print(df.groupby([df["pdate"].dt.month, "Rating"])["UserID"])
df_group = df.groupby([df["pdate"].dt.month, "Rating"])["UserID"].agg(pv=np.size)
# 对这样格式的数据，我想查看按月份，不同评分的次数趋势，是没法实现的
# 需要将数据变换成每个评分是一列才可以实现
print(df_group.head(10))

# 2. 使用unstack实现数据二维透视
# 目的：想要画图对比按照月份的不同评分的数量趋势
df_stack = df_group.unstack()
print(df_stack)
from matplotlib import pyplot as plt

_x = df_stack.index
_y_pv1 = df_stack.values[:,0]
_y_pv2 = df_stack.values[:,1]
_y_pv3 = df_stack.values[:,2]
_y_pv4 = df_stack.values[:,3]
_y_pv5 = df_stack.values[:,4]

plt.figure(figsize=(20,8),dpi=80)
plt.plot(range(len(_x)),_y_pv1,label = '(pv,1)')
plt.plot(range(len(_x)),_y_pv2,label = '(pv,2)')
plt.plot(range(len(_x)),_y_pv3,label = '(pv,3)')
plt.plot(range(len(_x)),_y_pv4,label = '(pv,4)')
plt.plot(range(len(_x)),_y_pv5,label = '(pv,5)')

plt.xticks(range(len(_x)),_x)
plt.legend(loc='best')
# plt.show()

# unstack和stack是互逆操作
print(df_stack.stack().head(20))

# 3. 使用pivot简化透视
print(df_group.head(20))
df_reset = df_group.reset_index()
print(df_reset.head())
df_pivot = df_reset.pivot('pdate','Rating','pv')
print(df_pivot.head())

_x = df_pivot.index
_y_1 = df_pivot.values[:,0]
_y_2 = df_pivot.values[:,1]
_y_3 = df_pivot.values[:,2]
_y_4 = df_pivot.values[:,3]
_y_5 = df_pivot.values[:,4]

plt.figure(figsize=(20,8),dpi=80)
plt.plot(range(len(_x)),_y_1,label = '1')
plt.plot(range(len(_x)),_y_2,label = '2')
plt.plot(range(len(_x)),_y_3,label = '3')
plt.plot(range(len(_x)),_y_4,label = '4')
plt.plot(range(len(_x)),_y_5,label = '5')

plt.xticks(range(len(_x)),_x)
plt.legend(loc='best')
# plt.show()
# pivot方法相当于对df使用set_index创建分层索引，然后调用unstack

# 4. stack、unstack、pivot的语法
# stack：DataFrame.stack(level=-1, dropna=True)，将column变成index，类似把横放的书籍变成竖放¶
# level=-1代表多层索引的最内层，可以通过==0、1、2指定多层索引的对应层
# unstack：DataFrame.unstack(level=-1, fill_value=None)，将index变成column，类似把竖放的书籍变成横放
# pivot：DataFrame.pivot(index=None, columns=None, values=None)，指定index、columns、values实现二维透视